﻿using SD.Infrastructure.EntityBase;
using SD.Toolkits.Recursion.Tree;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SlamDunk.MES.Domain.Entities.ResourceContext
{
    /// <summary>
    /// 物料类
    /// </summary>
    public class MaterialClass : AggregateRootEntity, ITree<MaterialClass>
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected MaterialClass()
        {
            //初始化导航属性
            this.SubNodes = new HashSet<MaterialClass>();
        }
        #endregion

        #region 01.创建物料类构造器
        /// <summary>
        /// 创建物料类构造器
        /// </summary>
        /// <param name="classNo">物料类编号</param>
        /// <param name="className">物料类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="materialSourceType">物料来源类型</param>
        /// <param name="description">描述</param>
        /// <param name="parentNode">上级节点</param>
        public MaterialClass(string classNo, string className, Guid? facilityId, MaterialSourceType? materialSourceType, string description, MaterialClass parentNode)
            : this()
        {
            base.Number = classNo;
            base.Name = className;
            this.FacilityId = facilityId;
            this.MaterialSourceType = materialSourceType;
            this.TreePath = this.GetTreePath();
            this.Description = description;
            this.ParentNode = parentNode;
            parentNode?.SubNodes.Add(this);

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #endregion

        #region # 属性

        #region 工厂模型Id —— Guid? FacilityId
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        public Guid? FacilityId { get; private set; }
        #endregion

        #region 物料来源类型 —— MaterialSourceType? MaterialSourceType
        /// <summary>
        /// 物料来源类型
        /// </summary>
        public MaterialSourceType? MaterialSourceType { get; private set; }
        #endregion

        #region 树路径 —— string TreePath
        /// <summary>
        /// 树路径
        /// </summary>
        public string TreePath { get; private set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 只读属性 - 是否是根级节点 —— bool IsRoot
        /// <summary>
        /// 只读属性 - 是否是根级节点
        /// </summary>
        public bool IsRoot
        {
            get { return this.ParentNode == null; }
        }
        #endregion

        #region 只读属性 - 是否是叶子级节点 —— bool IsLeaf
        /// <summary>
        /// 只读属性 - 是否是叶子级节点
        /// </summary>
        public bool IsLeaf
        {
            get { return !this.SubNodes.Any(x => !x.Deleted); }
        }
        #endregion

        #region 导航属性 - 上级节点 —— MaterialClass ParentNode
        /// <summary>
        /// 导航属性 - 上级节点
        /// </summary>
        public virtual MaterialClass ParentNode { get; private set; }
        #endregion

        #region 导航属性 - 下级节点集 —— ICollection<MaterialClass> SubNodes
        /// <summary>
        /// 导航属性 - 下级节点集
        /// </summary>
        public virtual ICollection<MaterialClass> SubNodes { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 修改物料类 —— void UpdateInfo(string classNo, string className...
        /// <summary>
        /// 修改物料类
        /// </summary>
        /// <param name="classNo">物料类编号</param>
        /// <param name="className">物料类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="materialSourceType">物料来源类型</param>
        /// <param name="description">描述</param>
        public void UpdateInfo(string classNo, string className, Guid? facilityId, MaterialSourceType? materialSourceType, string description)
        {
            base.Number = classNo;
            base.Name = className;
            this.FacilityId = facilityId;
            this.MaterialSourceType = materialSourceType;
            this.TreePath = this.GetTreePath();
            this.Description = description;

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #region 深度获取所有子节点Id列表 —— IList<Guid> GetDeepNodeIds()
        /// <summary>
        /// 深度获取所有子节点Id列表
        /// </summary>
        /// <returns>工厂模型Id列表</returns>
        /// <remarks>包括this.Id</remarks>
        public IList<Guid> GetDeepNodeIds()
        {
            ICollection<Guid> facilityIds = new HashSet<Guid>();

            ICollection<MaterialClass> deepSubNodes = this.GetDeepSubNodes();
            foreach (MaterialClass subNode in deepSubNodes)
            {
                facilityIds.Add(subNode.Id);
            }

            facilityIds.Add(this.Id);

            return facilityIds.ToList();
        }
        #endregion

        #region 初始化关键字 —— void InitKeywords()
        /// <summary>
        /// 初始化关键字
        /// </summary>
        private void InitKeywords()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(base.Number);
            builder.Append(base.Name);
            builder.Append(this.Description);

            base.SetKeywords(builder.ToString());
        }
        #endregion

        #region 重写ToString —— override string ToString()
        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>物料类名称</returns>
        public override string ToString()
        {
            return base.Number;
        }
        #endregion

        #endregion
    }
}
